package com.sihan.framework.etm.service.business.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.framework.model.PageResult;
import com.framework.mybatis.Condition;
import com.framework.mybatis.service.impl.BaseServiceImpl;
import com.framework.util.JsonUtils;
import com.framework.util.PageUtils;
import com.github.pagehelper.PageHelper;
import com.sihan.framework.etm.common.AppConfiguration;
import com.sihan.framework.etm.common.CacheOperatorInfo;
import com.sihan.framework.etm.common.util.*;
import com.sihan.framework.etm.dto.AtlasAnswerDTO;
import com.sihan.framework.etm.dto.SignDTO;
import com.sihan.framework.etm.dto.WorkTicketDTO;
import com.sihan.framework.etm.dto.baseData.DevicePostionDTO;
import com.sihan.framework.etm.dto.baseData.ToolDTO;
import com.sihan.framework.etm.dto.business.AtlasPositionDTO;
import com.sihan.framework.etm.dto.business.ToolPositonDTO;
import com.sihan.framework.etm.dto.business.WarehouseQueryReqDTO;
import com.sihan.framework.etm.entity.baseData.DeviceCoordinateRecordModel;
import com.sihan.framework.etm.entity.baseData.DeviceModel;
import com.sihan.framework.etm.entity.business.StationLacation;
import com.sihan.framework.etm.entity.business.ToolMoveCoordinateModel;
import com.sihan.framework.etm.entity.business.ToolPosition;
import com.sihan.framework.etm.enums.DeviceType;
import com.sihan.framework.etm.mapper.baseData.DeviceCoordinateMapper;
import com.sihan.framework.etm.mapper.baseData.DeviceMapper;
import com.sihan.framework.etm.mapper.business.StationLocationMapper;
import com.sihan.framework.etm.mapper.business.ToolPositionMapper;
import com.sihan.framework.etm.service.baseData.DeviceService;
import com.sihan.framework.etm.service.business.ToolPositionService;
import com.sihan.framework.etm.service.workTicket.WorkTicketService;
import com.sihan.framework.etm.vo.ToolIocationMode;
import com.sihan.framework.etm.vo.baseData.DeviceBindRecordVO;
import com.sihan.framework.etm.vo.baseData.DevicePositionVO;
import com.sihan.framework.etm.vo.business.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;

@Component
@Slf4j
public class ToolPositionServiceImpl extends BaseServiceImpl<ToolPosition, String> implements ToolPositionService {
    protected final static Double EARTH_RADIUS = 6378.137;//地球半径
    @Autowired
    private ToolPositionMapper toolPositionMapper;

    @Autowired
    private StationLocationMapper stationLocationMapper;

    @Autowired
    private AppConfiguration appConfig;

    @Autowired
    private DeviceMapper deviceMapper;

//    @Autowired
//    private OrgMapper orgMapper;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private DeviceCoordinateMapper deviceCoordinateMapper;
    @Autowired
    private WorkTicketService workTicketService;

    /**
     * @param lng
     * @param lat
     * @param lngOther
     * @param latOther
     * @return
     * @return Double
     * @description 计算两个点的坐标距离 计算结果为千米
     * @auther 韩兵
     * @Date 2020年8月27日
     */
    public static Double calcutLocation(Double lng, Double lat, Double lngOther, Double latOther) {
        double lon1 = (Math.PI / 180) * lng;
        double lon2 = (Math.PI / 180) * lngOther;
        double lat1 = (Math.PI / 180) * lat;
        double lat2 = (Math.PI / 180) * latOther;

        return (Math.acos(Math.sin(lat1) * Math.sin(lat2) +
                Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)) * EARTH_RADIUS) * 1000;
    }

    @Override
    public ToolPositionDetailVO selectToolCoordinateInfoById(String id) {
        ToolPositionDetailVO vo = toolPositionMapper.selectToolCoordinateInfoById(id);
        //vo.setWarehouseStatus(vo.getInWarehouse()?"已入库":"已出库");
        return vo;
    }

    @Override
    public PageResult<ToolPositionDetailVO> selectPage(ToolPositonDTO dto) {
        PageHelper.startPage(dto);
        List<ToolPositionDetailVO> result = toolPositionMapper.selectPage(dto);
        return PageUtils.toPageResult(result);
    }

    @Override
    public Map<String, ToolPositionMapVO> selectToolCoordinateForMap(ToolPositonDTO dto) {
        Map<String, ToolPositionMapVO> common = new HashMap<String, ToolPositionMapVO>();
        //List<DevicePositionVO> details = toolPositionMapper.selectDeviceCoordinateForMap(dto);
//		if(null != details && !details.isEmpty()) {
//			Map<String,List<DevicePositionVO>> typeDetails = details.stream().
//					collect(Collectors.groupingBy(DevicePositionVO::getModelCode));
//			Iterator<Entry<String,List<ToolPositionDetailVO>>> ite = typeDetails.entrySet().iterator();
//			while(ite.hasNext()) {
//				Entry<String,List<ToolPositionDetailVO>> one = ite.next();
//				ToolPositionMapVO vo = new ToolPositionMapVO();
//				vo.setModelCode(one.getKey());
//				vo.setDetails(one.getValue());
//				common.put("a"+one.getKey(), vo);
//			}
//			return common;
//		}
        return common;
    }

    @Override
    public PageResult<ToolWarehouseRecordVO> selectWarehouseRecord(WarehouseQueryReqDTO dto) {
        if (!StringUtils.isBlank(dto.getInQueryStartTime())) {
            dto.setInQueryStartTime(dto.getInQueryStartTime() + " 00:00:00:000");
        }
        if (!StringUtils.isBlank(dto.getInQueryEndTime())) {
            dto.setInQueryEndTime(dto.getInQueryEndTime() + " 23:59:59:999");
        }
        if (!StringUtils.isBlank(dto.getOutQueryStartTime())) {
            dto.setOutQueryStartTime(dto.getOutQueryStartTime() + " 00:00:00:000");
        }
        if (!StringUtils.isBlank(dto.getOutQueryEndTime())) {
            dto.setOutQueryEndTime(dto.getOutQueryEndTime() + " 23:59:59:999");
        }
        PageHelper.startPage(dto);
        List<ToolWarehouseRecordVO> result = toolPositionMapper.selectWarehouseRecord(dto);
        return PageUtils.toPageResult(result);
    }

    @Override
    public List<ToolTrajectoryVO> selectToolCoorHistory(ToolDTO dto) {

        List<ToolTrajectoryVO> li = toolPositionMapper.selectToolCoorHistory(dto, 50, null);

        return li;
    }

    @Override
    public Map trackSign(ToolDTO dto) {
        HashMap<Object, Object> map = new HashMap<>();
        List<ToolTrajectoryVO> li = toolPositionMapper.selectToolCoorHistory(dto, 50, null);
        List<SignDTO> SignS = new ArrayList<>();
        WorkTicketDTO byDevId = workTicketService.findByDevId(dto.getId());
        if (null != byDevId && null != byDevId.getLngLat()) {
            String lngLat = byDevId.getLngLat();
            String[] split = lngLat.split(";");
            for (String s : split) {
                if (null != s && !"".equals(s)) {
                    SignDTO sign = new SignDTO();
                    ToolTrajectoryVO vo = new ToolTrajectoryVO();
                    String[] split1 = s.split(",");
                    sign.setLat(split1[0]);
                    sign.setLng(split1[1]);
                    SignS.add(sign);
                }
            }
        }
        map.put("track", li);
        map.put("sign", SignS);
        return map;
    }

    //{ startX: 0.0, startY: 0.0, endX: 100.0, endY: 100.0 },
    //{ startX: 100.0, startY: 100.0, endX: 220.0, endY: 100.0 },
    //{ startX: 220.0, startY: 100.0, endX: 220.0, endY: 230.0 },
    //{ startX: 220.0, startY: 230.0, endX: 260.0, endY: 230.0 }
    @Override
    public List<ToolMoveCoordinateModel> lngLatToCoordinate(ToolDTO dto) {
        List<ToolMoveCoordinateModel> result = new ArrayList<ToolMoveCoordinateModel>();
        List<ToolTrajectoryVO> historys = toolPositionMapper.selectToolCoorHistory(dto, 50, null);
        List<StationLacation> stations = stationLocationMapper.selectList(new Condition<StationLacation>());
        if (null != stations && !stations.isEmpty()) {
            String locations = stations.get(0).getLocation();
            String[] locationss = locations.split(";");
            for (ToolTrajectoryVO history : historys) {
                String coorHis = history.getLng() + "," + history.getLat();
                for (int k = 0; k < locationss.length; k++) {
                    if (coorHis.equals(locationss[k])) {
                        ToolMoveCoordinateModel coor = new ToolMoveCoordinateModel();
                        int x = k / appConfig.getGrisXlenght();
                        int y = k % appConfig.getGrisXlenght();
                        coor.setStartX(x);
                        coor.setStartY(y);
                        if (!result.isEmpty()) {
                            result.get(result.size() - 1).setEndX(x);
                            result.get(result.size() - 1).setEndY(y);
                        }
                        result.add(coor);
                        break;
                    }
                }
            }
        }
        result.remove(result.size() - 1);
        return result;
    }

    @Override
    public List<List<Object>> lngLatToCoordinateArray(ToolDTO dto) {
        List<List<Object>> result = new ArrayList<List<Object>>();
        List<ToolTrajectoryVO> historys = toolPositionMapper.selectToolCoorHistory(dto, 50, null);
        List<StationLacation> stations = stationLocationMapper.selectList(new Condition<StationLacation>());
        if (null != stations && !stations.isEmpty()) {
            String locations = stations.get(0).getLocation();
            String[] locationss = locations.split(";");
            for (ToolTrajectoryVO history : historys) {
                String coorHis = history.getLngLat();
                for (int k = 0; k < locationss.length; k++) {
                    //String[] lngLat = locationss[k].split(",");
                    //if(lngLat[0].equals(history.getLng()) && lngLat[1].equals(history.getLat())) {
                    if (coorHis.equals(locationss[k])) {
                        int x = k / appConfig.getGrisXlenght();
                        int y = k % appConfig.getGrisXlenght();
                        List<Object> ele = new ArrayList<Object>();
                        ele.add(x * 120);
                        ele.add(y * 60);
                        result.add(ele);
                        break;
                    }
                }
            }
        }
        return result;
    }

    @SuppressWarnings({"unchecked"})
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPositionRecord(JSONObject jsonObject,Date date) {
        Map<String, Object> body = null;
        try {
            boolean success = sgmap.init();
            if (success) {
                System.out.println("鉴权组件初始化成功");
            }
        } catch (Exception e) {
            log.error("鉴权组件初始化失败", e);
        }
        try {
            body = JsonUtils.readFromJson(StringEscapeUtils.unescapeHtml(jsonObject.get("payload").toString()), HashMap.class);
            if(jsonObject.containsKey("time") && null != jsonObject.get("time")){
                System.out.println(DateUtils.getInstance().getDateStr(date,DateUtils.getInstance().SDF));
            }
        } catch (IOException e) {
            log.error("解析消息异常", e);
        }
        if (null != body && !body.isEmpty()) {
            if (body.containsKey("data")) {
                Object data = body.get("data");
                ToolIocationMode mode = null;
                try {
                    if (data instanceof Map) {
                        // 如果 data 是一个 Map 对象，直接反序列化为 ToolIocationMode 对象
                        mode = JsonUtils.readFromJson(JsonUtils.toJsonString(data), ToolIocationMode.class);
                    } else if (data instanceof String) {
                        // 如果 data 是一个 JSON 字符串，则先解析字符串再反序列化
                        mode = JsonUtils.readFromJson((String) data, ToolIocationMode.class);
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                String deviceId = mode.getId();
                log.info("收到设备:[" + deviceId + "]定位数据:{" + data + "}");
                DeviceModel device = deviceMapper.selectOne(new Condition<>().eq("communication_code", deviceId).eq("is_delete", 0));
                if (null != device) {
                    //米级定位：type=6001; BC20 通过发送次数计算电量
                    //分米级定位：type=6002; RTK 通过电压计算电量  有三项挂接数据
                    //安全帽：type=6003; 通过发送次数计算电量  有近电报警
                    //警示牌：type=6004; 通过发送次数计算电量
                    //警示牌－只测电压的警示牌：type=600５; 通过电压计算电量（）
                    device.setTypeCommondCode(mode.getType());
                    if ("6002".equals(mode.getType())) {
                        //电压 实际值=该值/100
                        device.setVoltage(new BigDecimal(null == mode.getVoltage() ? 0 : Integer.parseInt(mode.getVoltage()))
                                .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                        //通过电压计算电量
                        device.setElectricityPercent(QuantityUtils.formattedQuantity(device.getVoltage()));
                    }if ("6005".equals(mode.getType())) {
                        //电压 实际值=该值/100
                        device.setVoltage(new BigDecimal(null == mode.getVoltage() ? 0 : Integer.parseInt(mode.getVoltage()))
                                .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                        //通过电压计算电量
                        String[] voltageRange = appConfig.getJinshipaiVoltageRange().split(";");
                        device.setElectricityPercent(QuantityUtils.formattedNewQuantity(device.getVoltage(),new BigDecimal(voltageRange[0]),new BigDecimal(voltageRange[1])));
                    } else {
                        //电压 实际值=该值/100
                        device.setVoltage(new BigDecimal(null == mode.getVoltage() ? 0 : Integer.parseInt(mode.getVoltage()))
                                .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                        device.setElectricityPercent(QuantityUtils.formattedQuantity(device.getVoltage()));
                        //通过发送次数计算电量
                        if (null != mode.getCount() && Integer.parseInt(mode.getCount()) > 0) {
                            LocalDate now = LocalDate.now();
                            LocalDate existSendDate = null == device.getSendNewTime() ? now :
                                    device.getSendNewTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                            if (device.getSendCount() > Integer.parseInt(mode.getCount()) || null == device.getSendNewTime()) {
                                device.setSendNewTime(date);
                            }
                            Long days = now.toEpochDay() - existSendDate.toEpochDay();
                            device.setSendCount(Integer.parseInt(mode.getCount()));
                            device.setElectricityPercent(this.calculateVoltage(Integer.parseInt(mode.getCount()), days.intValue()));
                        }
                    }
                    //经度
                    //纬度
                    BigDecimal lng = null;
                    BigDecimal lnt = null;
                    DeviceCoordinateRecordModel record = new DeviceCoordinateRecordModel();
                    if (!"0".equals(mode.getLatitude()) && !"0".equals(mode.getLongitude())) {
                        String coorOld = mode.getLongitude()+","+mode.getLatitude();
                        //判断是否是十进制度格式
                        if (!DecimalDegreeValidator.isRational(coorOld)){
                            coorOld =  Double.parseDouble(mode.getLongitude())/ 1000000.00 + "," + Double.parseDouble(mode.getLatitude()) / 1000000.00;
                        }
                        //3-31String[] coors  = SpaceCoordinatesUtil.changeSpaceCoordinates(coorOld).split(",");放开
                         //String[] coors  = SpaceCoordinatesUtil.changeSpaceCoordinates(coorOld).split(",");

                        try {
                            String coors = sgmap.coorTrans(coorOld);
                            // 创建 ObjectMapper 实例
                            ObjectMapper objectMapper = new ObjectMapper();
                            JsonNode rootNode = objectMapper.readTree(coors);
                            // 获取 "value" 数组
                            JsonNode valueArray = rootNode.path("value");
                            // 遍历数组并获取 x 和 y 的值
                            for (JsonNode item : valueArray) {
                                lng = item.path("x").decimalValue();
                                lnt = item.path("y").decimalValue();
                            }
                        } catch(Exception e) {
                            e.printStackTrace();
                        }
                        if (lnt.doubleValue() > 1) {
                            device.setInitialLat(lnt);
                        }
                        if (lng.doubleValue() > 1) {
                            device.setInitialLng(lng);
                        }
                        record.setLngLat(Arrays.toString(new BigDecimal[]{lng, lnt}));

                        record.setCreateTime(date);
                        record.setDeviceId(device.getId());
                        if (null != lng) {
                            record.setLat(lnt.doubleValue());
                            record.setLng(lng.doubleValue());
                        } else {
                            record.setLat(0.0);
                            record.setLng(0.0);
                        }

                        record.setVoltage(device.getVoltage());
                        record.setSendCount(device.getSendCount());
                        record.setTemperature(BigDecimal.valueOf(Integer.parseInt(mode.getTemperature()) / 100.0));

                        if (!"4001".equals(mode.getType()) && null != mode.getHeight() && !"".equals(mode.getHeight())) {
                            BigDecimal bigDecimal = new BigDecimal(mode.getHeight());
                            BigDecimal divide = bigDecimal.divide(new BigDecimal(10), RoundingMode.HALF_UP);
                            device.setInitialHeight(divide);
                            record.setHeight(divide);
                        }
                        if ("4001".equals(mode.getType())) {
                            BigDecimal bigDecimal = new BigDecimal(mode.getHeight());
                            device.setInitialHeight(bigDecimal);
                            record.setHeight(bigDecimal);
                        }

                        //定位精度
                        record.setPositionalAccuracy(Integer.parseInt(mode.getPrecision()));
                        deviceCoordinateMapper.insert(record);
                    }
                }
                if (null != device) {
                    deviceMapper.updateById(device);
                }
            } else {
                Integer voltage = Integer.valueOf(body.get("voltage").toString());
                Integer sendCount = Integer.valueOf(body.get("count").toString());
                DeviceModel device = null;
                String deviceId = null;
                if (body.get("deviceID") != null) {
                    deviceId = body.get("deviceID").toString();
                } else if (body.get("id") != null) {
                    deviceId = body.get("id").toString();
                } else if (body.get("deviceId") != null) {
                    deviceId = body.get("deviceId").toString();
                } else {
                    return;
                }
                Integer temperature = Integer.valueOf(body.get("temperature").toString());
                Double height = Double.valueOf(body.get("height").toString());
                String toolId = null;
                try {
                    device = deviceMapper.selectOne(new Condition<>().eq("communication_code", deviceId).eq("is_delete", 0));
                    if (null != device) {
                        toolId = device.getId();
                        device.setVoltage(new BigDecimal(null == voltage ? 0 : voltage).
                                divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                        if (null != sendCount && sendCount > 0) {
                            LocalDate now = LocalDate.now();
                            LocalDate existSendDate = null == device.getSendNewTime() ? now :
                                    device.getSendNewTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                            if (device.getSendCount() > sendCount || null == device.getSendNewTime()) {
                                device.setSendNewTime(date);
                            }
                            device.setSendCount(sendCount);
                            Long days = now.toEpochDay() - existSendDate.toEpochDay();
                            //通过发送次数计算电量
                            device.setElectricityPercent(this.calculateVoltage(sendCount, days.intValue()));
                            //通过电压计算电量
                            //device.setElectricityPercent(QuantityUtils.formattedQuantity(device.getVoltage()));
                        }else{
                            //通过电压计算电量
                            device.setElectricityPercent(QuantityUtils.formattedQuantity(device.getVoltage()));
                        }
                    }
                } catch (Exception e) {
                    log.error("更新电池电量和发送次数异常", e);
                }
                if (null != toolId && Double.valueOf(body.get("latitude").toString())  != 0) {
                    Integer year = Integer.parseInt(body.get("year").toString());
                    Integer month = Integer.parseInt(body.get("month").toString());
                    Integer day = Integer.parseInt(body.get("day").toString());
                    Integer h = Integer.parseInt(body.get("hour").toString());
                    Integer m = Integer.parseInt(body.get("minute").toString());
                    Integer s = Integer.parseInt(body.get("second").toString());
                    String strYear = "20" + year;
                    Calendar c = Calendar.getInstance();
                    c.set(Calendar.YEAR, Integer.parseInt(strYear));
                    c.set(Calendar.MONTH, month);
                    c.set(Calendar.DAY_OF_MONTH, day);
                    c.set(Calendar.HOUR_OF_DAY, h);
                    c.set(Calendar.MINUTE, m);
                    c.set(Calendar.SECOND, s);
                    c.set(Calendar.MILLISECOND, 0);
                    body.put("toolId", toolId);
                    String coorOld = body.get("longitude")+","+body.get("latitude");
                    //判断是否是十进制度格式
                    if (!DecimalDegreeValidator.isRational(coorOld)){
                        coorOld = (Double)body.get("longitude") / 1000000.00 + "," + (Double)body.get("latitude") / 1000000.00;
                    }
                    BigDecimal lng = null;
                    BigDecimal lnt = null;
                    try {
                        String coors = sgmap.coorTrans(coorOld);
                        // 创建 ObjectMapper 实例
                        ObjectMapper objectMapper = new ObjectMapper();
                        JsonNode rootNode = objectMapper.readTree(coors);
                        // 获取 "value" 数组
                        JsonNode valueArray = rootNode.path("value");
                        // 遍历数组并获取 x 和 y 的值
                        for (JsonNode item : valueArray) {
                            lng = item.path("x").decimalValue();
                            lnt = item.path("y").decimalValue();
                        }
                    } catch(Exception e) {
                        e.printStackTrace();
                    }
                    if (lnt.doubleValue() > 1) {
                        device.setInitialLat(lnt);
                    }
                    if (lng.doubleValue() > 1) {
                        device.setInitialLng(lng);
                    }
                    //检查是否重复
                    DeviceCoordinateRecordModel record = deviceCoordinateMapper.selectOne(new Condition<DeviceCoordinateRecordModel>().
                            eq("create_time", c.getTime()).eq("device_id", toolId));
                    if (null == record) {
                        record = new DeviceCoordinateRecordModel();
                        record.setCreateTime(date);
                        record.setDeviceId(toolId);
                        record.setLat(lnt.doubleValue());
                        record.setLng(lng.doubleValue());
                        record.setLngLat(lng + "," + lnt);
                        record.setVoltage(new BigDecimal(voltage / 100.00));
                        record.setSendCount(sendCount);
                        record.setTemperature(new BigDecimal(temperature / 100.0));
                        BigDecimal divide = new BigDecimal(height).divide(new BigDecimal(10), RoundingMode.HALF_UP);
                        device.setInitialHeight(divide);
                        record.setHeight(divide);
                        record.setPositionalAccuracy(Integer.parseInt(body.get("precision").toString()));
                        deviceCoordinateMapper.insert(record);

                    }
                }
                if (null != device) {
                    try {
                        deviceMapper.updateById(device);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }

        }

    }



    @Override
    public List<DevicePositionVO> selectArrayToolCoordinateForMap(DevicePostionDTO dto) {
        String orgIds = (String) CacheOperatorInfo.getMapValue(EtmWebUtil.userId(), null);
        if (StringUtils.isBlank(orgIds)) {
            return null;
        }
        return toolPositionMapper.selectDeviceCoordinateForMap(dto, orgIds.split(","));
    }

    @Override
    public List<AtlasAnswerDTO> selectArrayToolMap(AtlasPositionDTO dto) {
        String orgIds = (String) CacheOperatorInfo.getMapValue(EtmWebUtil.userId(), null);
        List<String> strings = new ArrayList<>();

        //如果时间为空 就只展示当天的挂接异常
        List<AtlasAnswerDTO> ls = toolPositionMapper.selectAtlasLIst(strings, dto,null);
        formatMarkers(ls);
        Collections.sort(ls);
        //对电量进行计算
        if (ls.size() > 0) {
            for (AtlasAnswerDTO devDTO : ls) {
                if (null != devDTO.getVoltage()) {
                    BigDecimal bigDecimal = QuantityUtils.formattedQuantity(devDTO.getVoltage());
                    devDTO.setElectricQuantity(String.valueOf(bigDecimal));
                }
            }
        }
        return ls;
    }

    /**
     * 根据地图 拖动加载设备数据
     *
     * @param atlDto
     * @return
     */
    @Override
    public List<AtlasAnswerDTO> selectArrayToolCoordinateForMap(AtlasPositionDTO atlDto) {
        String orgIds = (String) CacheOperatorInfo.getMapValue(EtmWebUtil.userId(), null);
        String polygon = "";
        //构建多边形
        try {
            polygon = formattingPolygon(atlDto);
        } catch (Exception e) {
            log.info("构建多边形出现异常!");
            e.printStackTrace();
            return null;
        }
        if ("".equals(polygon)) {
            return null;
        }
        List<String> strings = toolPositionMapper.selectAtlasIds(null, polygon);
        List<AtlasAnswerDTO> ls = null;
        if (strings.size() > 0) {
            //拖动加载设备 不需要查询条件
            //atlDto = new AtlasPositionDTO();
            ls = toolPositionMapper.selectAtlasLIst(strings, atlDto, null);
            formatMarkers(ls);
            Collections.sort(ls);
            //对电量进行计算
            if (ls.size() > 0) {
                for (AtlasAnswerDTO devDTO : ls) {
                    if (null != devDTO.getVoltage()) {
                        BigDecimal bigDecimal = QuantityUtils.formattedQuantity(devDTO.getVoltage());
                        devDTO.setElectricQuantity(String.valueOf(bigDecimal));
                    }
                }
            }
        }
        return ls;
    }


    /**
     * 微信获取地图定位
     *
     * @param query
     * @return
     */
    @Override
    public List<LocalizerVO> wxMap(String query) {
        String orgIds = (String) CacheOperatorInfo.getMapValue(EtmWebUtil.userId(), null);
//        AtlasPositionDTO atlDto = new AtlasPositionDTO();
//        atlDto.setName(query);
//        String[] split2 = orgIds.split(",");
//        List<String> list = Arrays.asList(split2);
//        toolPositionMapper.selectAtlasLIst(list, atlDto, null);
        List<LocalizerVO> vos = toolPositionMapper.wxMap(orgIds.split(","), query);
        for (LocalizerVO vo : vos) {
            if (vo.getLongitude() != null && !"".equals(vo.getLongitude()) && vo.getLatitude() != null && !"".equals(vo.getLatitude())) {
                String s = map_bd2tx(vo.getLongitude(), vo.getLatitude());
                String[] split = s.split(",");
                vo.setLongitude(split[0]);
                vo.setLatitude(split[1]);
            }
            WXlocalizerDtl dtl = vo.getDtl();
            if (null != dtl) {
                if (dtl.getLng() != null && !"".equals(dtl.getLng()) && dtl.getLat() != null && !"".equals(dtl.getLat())) {
                    String s = map_bd2tx(dtl.getLng(), dtl.getLat());
                    String[] split = s.split(",");
                    dtl.setLng(split[0]);
                    dtl.setLat(split[1]);
                }
                if (DeviceType.GroundWire.equals(dtl.getTypeId())) {
                    if (null == dtl.getMountState() || 0 == dtl.getMountState()){
                        dtl.setHitchA("0");
                        dtl.setHitchB("0");
                        dtl.setHitchC("0");
                        dtl.setHitchABC("0,0,0");
                        dtl.setState(2);
                        dtl.setMountTypeS("未挂接");
                    }
                }
                this.AbnormalType(dtl);
                String hitchABC = dtl.getHitchABC();
                if (null != hitchABC && !"".equals(hitchABC)) {
                    String[] split1 = hitchABC.split(",");
                    dtl.setHitchA(split1[0]);
                    dtl.setHitchB(split1[1]);
                    dtl.setHitchC(split1[2]);
                    if ("1,1,1".equals(hitchABC)) {
                        dtl.setState(1);
                    } else if ("0,0,0".equals(hitchABC)) {
                        dtl.setState(2);
                    } else {
                        dtl.setState(0);
                    }
                } else {
                    dtl.setHitchA("0");
                    dtl.setHitchB("0");
                    dtl.setHitchC("0");
                    if (null == dtl.getState()) {
                        dtl.setState(2);
                    }
                }
            }
            if (!DeviceType.GroundWire.equals(dtl.getTypeId())) {
                if (null != dtl.getState() && 1 != dtl.getState()) {
                    dtl.setState(2);
                } else {
                    dtl.setState(1);
                }
            }
        }
        return vos;
    }

    /**
     * 微信小程序 获取地图轨迹
     *
     * @return
     */
    @Override
    public List<WXCoordinateVO> getWXCoordinateList(ToolDTO dto) {
        if ("undefined".equals(dto.getQueryStartTime())) {
            dto.setQueryStartTime(null);
        }
        if ("undefined".equals(dto.getQueryEndTime())) {
            dto.setQueryEndTime(null);
        }
        List<WXCoordinateVO> li = toolPositionMapper.getWXCoordinateList(dto, null, null);
        for (WXCoordinateVO vo : li) {
            map_bd2tx(vo);
        }
        return li;
    }

    /**
     * 百度地图坐标转微信地图坐标
     *
     * @param vo
     */
    public void map_bd2tx(WXCoordinateVO vo) {
        double x_pi = 3.14159265358979324;
        double x = Double.parseDouble(vo.getLongitude()) - 0.0065,
                y = Double.parseDouble(vo.getLatitude()) - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        vo.setLatitude(String.valueOf(z * Math.sin(theta)));
        vo.setLongitude(String.valueOf(z * Math.cos(theta)));
    }

    public String map_bd2tx(String longitude, String latitude) {
        double x_pi = 3.14159265358979324;
        double x = Double.parseDouble(longitude) - 0.0065,
                y = Double.parseDouble(latitude) - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        return z * Math.cos(theta) + "," + z * Math.sin(theta);
    }

    @Override
    public PageResult<DeviceBindRecordVO> selectDeviceBindRecord(DevicePostionDTO dto) {
        PageHelper.startPage(dto);
        List<DeviceBindRecordVO> result = toolPositionMapper.selectDeviceBindRecord(dto);
        return PageUtils.toPageResult(result);
    }

    /**
     * 通过发送次数与待机天数计算电量
     *
     * @param sendCount 发送的次数
     * @param waitDays  待机天数
     * @return
     * @return BigDecimal
     * @description //剩余电量 //S =（M-x-y*A)/M
     * @auther 韩兵
     * @Date 2021年6月4日
     */
    public BigDecimal calculateVoltage(Integer sendCount, Integer waitDays) {
        Integer m = appConfig.getVoltageCount();
        Integer n = appConfig.getVoltageWaitDays();
        BigDecimal a = new BigDecimal(m).divide(new BigDecimal(n), 3, RoundingMode.HALF_UP);
        BigDecimal x = new BigDecimal(sendCount).divide(new BigDecimal(4), 3, RoundingMode.HALF_UP);
        BigDecimal electricity = (new BigDecimal(m).subtract(x).subtract(
                new BigDecimal(waitDays).multiply(a))).divide(new BigDecimal(m), 3, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
        return electricity;
    }


    /**
     * 对三项进行处理
     */
    public void formatMarkers(List<AtlasAnswerDTO> ls) {
        for (AtlasAnswerDTO vo : ls) {
            //判断是否是结束挂载
            if (DeviceType.GroundWire.equals(vo.getTypeId()) || DeviceType.SDGroundWire.equals(vo.getTypeId())) {
                if (null == vo.getMountState() || 0 == vo.getMountState()){
                    vo.setHitchA("0");
                    vo.setHitchB("0");
                    vo.setHitchC("0");
                    vo.setHitchABC("0,0,0");
                    vo.setState(2);
                    vo.setMountTypeS("未挂接");
                }
                String hitchAbc = vo.getHitchABC();
                this.AbnormalTypes(vo);
                List<Object> li = new ArrayList<>();
                if (null != hitchAbc) {
                    String[] split1 = hitchAbc.split(",");
                    vo.setHitchA(split1[0]);
                    vo.setHitchB(split1[1]);
                    vo.setHitchC(split1[2]);
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("name","A");
                    jsonObject.put("value",split1[0].equals("0") ? "未挂接":"已挂接" );
                    li.add(jsonObject);

                    JSONObject jsonObject1 = new JSONObject();
                    jsonObject1.put("name","B");
                    jsonObject1.put("value",split1[1].equals("0") ? "未挂接":"已挂接" );
                    li.add(jsonObject1);

                    JSONObject jsonObject2 = new JSONObject();
                    jsonObject2.put("name","C");
                    jsonObject2.put("value",split1[2].equals("0") ? "未挂接":"已挂接" );

                    li.add(jsonObject2);
                    if ("1,1,1".equals(hitchAbc) && "1".equals(vo.getHitchD())) {
                        vo.setState(1);
                    } else if ("0,0,0".equals(hitchAbc)) {
                        vo.setMountTypeS("未挂接");
                        vo.setState(2);
                    } else {
                        vo.setState(0);
                    }
                } else {
                    vo.setHitchA("0");
                    vo.setHitchB("0");
                    vo.setHitchC("0");
                    if (null == vo.getState()) {
                        vo.setState(2);
                        vo.setMountTypeS("未挂接");
                    }
                    JSONObject a = new JSONObject();
                    a.put("name","A");
                    a.put("value","未挂接");
                    li.add(a);
                    JSONObject b = new JSONObject();
                    b.put("name","B");
                    b.put("value","未挂接");
                    li.add(b);
                    JSONObject c = new JSONObject();
                    c.put("name","C");
                    c.put("value","未挂接");
                    li.add(c);
                }
                vo.setHitch(li);
                if (DeviceType.SDGroundWire.equals(vo.getTypeId())) {
                    String mountGround = vo.getMountGround();
                    if (null != mountGround && !"".equals(mountGround)){
                        String[] split = mountGround.split(",");
                        int count = 1;
                        StringBuilder ground = new StringBuilder();
                        for (String str :split){
                            ground.append(count).append(" :").append(str.equals("0") ? "未接地 " : "已接地 ");
                            count ++;
                        }
                        vo.setGroundList(ground.toString());
                    }
                } else if(DeviceType.GroundWire.equals(vo.getTypeId())){
                    vo.setGroundList(vo.getGroundType());
                }
            }else if(DeviceType.SafetyHat.equals(vo.getTypeId())){
                if ( null != vo.getMountState()  && 1 == vo.getMountState()){
                    vo.setState(1);
                }else {
                    vo.setState(0);
                }
                this.AbnormalTypes(vo);
            }else if(DeviceType.WarningSign.equals(vo.getTypeId())){
                if ( null != vo.getMountState()  && 1 == vo.getMountState()){
                    vo.setState(1);
                }else {
                    vo.setState(0);
                }
                this.AbnormalTypes(vo);
            }

        }
    }

    public void AbnormalType(WXlocalizerDtl vo) {
        //智能接地线
        if (DeviceType.GroundWire.equals(vo.getTypeId())) {
            //判断三项挂接数
            Integer in = splitABC(vo.getHitchABC());
            if (null == vo.getState() && 0 == in) {
                vo.setAbnormalType("x_G0");
                vo.setGroundType("未接地");
            }
            //接地端挂载三项挂载
            if (null != vo.getState() && 1 == vo.getState()) {
                vo.setAbnormalType("xZ_G3");
                vo.setGroundType("已接地");
            } else
                //接地端挂载三项异常挂载
                if (null != vo.getState() && 0 == vo.getState()) {
                    //接地端与三项均未挂载
                    vo.setAbnormalType("xZ_G" + in);
                    vo.setGroundType("已接地");
                } else {
                    //接地端未挂载 判断三项是否正常
                    vo.setAbnormalType("x_G" + in);
                    vo.setGroundType("未接地");
                }
        }
        //安全帽
        if (DeviceType.SafetyHat.equals(vo.getTypeId())) {
            if (null != vo.getState() && 0 == vo.getState()) {
                vo.setAbnormalType("mW");
            } else {
                vo.setAbnormalType("mR");
            }
        }
        //WarningSign
        if (DeviceType.WarningSign.equals(vo.getTypeId())) {
            if (null != vo.getState() && 0 == vo.getState()) {
                vo.setAbnormalType("pW");
            } else {
                vo.setAbnormalType("pR");
            }
        }
    }

    /**
     * 演示版本 - 判断前端异常显示图片
     * 安全帽 两种类型 近电报警-mW  正常 -mR
     * 标识牌 两种类型 有电危险-pW  线路检修 -pR
     * 智能接地线
     * 接地端与三项均未挂载-x_G0
     * 接地端未挂载一项挂载-x_G1
     * 接地端未挂载二项挂载-x_G2
     * 接地端未挂载三项挂载-x_G3
     * 接地端挂载三项未挂载-xZ_G0
     * 接地端挂载一项挂载-xZ_G1
     * 接地端挂载二项挂载-xZ_G2
     * 接地端挂载三项挂载-xZ_G3
     *
     * @param vo
     */
    public void AbnormalTypes(AtlasAnswerDTO vo) {
        //智能接地线
        if (DeviceType.GroundWire.equals(vo.getTypeId()) || DeviceType.SDGroundWire.equals(vo.getTypeId())) {
            //判断三项挂接数
            Integer in = splitABC(vo.getHitchABC());
            if (null == vo.getState() && 0 == in) {
                vo.setAbnormalType("x_G0");
                vo.setHitchD("0");
                vo.setGroundType("未接地");
            }
            //接地端挂载三项挂载
            if (null != vo.getState() && 1 == vo.getState()) {
                vo.setAbnormalType("xZ_G3");
                vo.setHitchD("1");
                vo.setGroundType("已接地");
            } else
                //接地端挂载三项异常挂载
                if (null != vo.getState() && 0 == vo.getState()) {
                    //接地端与三项均未挂载
                    vo.setAbnormalType("xZ_G" + in);
                    vo.setHitchD("1");
                    vo.setGroundType("已接地");
                } else {
                    //接地端未挂载 判断三项是否正常
                    vo.setAbnormalType("x_G" + in);
                    vo.setHitchD("0");
                    vo.setGroundType("未接地");
                }
        }
        //安全帽
        if (DeviceType.SafetyHat.equals(vo.getTypeId())) {
            if (null != vo.getState() && 0 == vo.getState()) {
                vo.setState(1);
                vo.setAbnormalType("mW");
                vo.setMountTypeS("正常");
            } else {
                vo.setMountTypeS("近电告警");
                vo.setAbnormalType("mR");
                vo.setState(0);
            }
        }
        //WarningSign
        if (DeviceType.WarningSign.equals(vo.getTypeId())) {
            if (null != vo.getState() && 0 == vo.getState()) {
                vo.setState(1);
                vo.setAbnormalType("pW");
                vo.setMountTypeS("正常");
            } else {
                vo.setAbnormalType("pR");
                vo.setMountTypeS("有电危险");
                vo.setState(0);
            }
        }
    }

    /**
     * 判断三项中有几项挂接
     *
     * @return
     */
    public Integer splitABC(String hitchAbc) {
        int i = 0;
        if (null == hitchAbc) {
            return i;
        }
        String[] split = hitchAbc.split(",");
        for (String s : split) {
            if ("1".equals(s)) {
                i = i + 1;
            }
        }
        return i;
    }

    /**
     * 格式化 前端 传过来的JSON格式的 经纬度
     *
     * @param jsonString
     * @return
     */
    public String formattingLonLat(String jsonString) {
        String appJson = StringEscapeUtils.unescapeHtml(jsonString);//appJson
        com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(appJson);
        BigDecimal lat = (BigDecimal) jsonObject.get("lat");
        BigDecimal lng = (BigDecimal) jsonObject.get("lng");
        return lng + " " + lat;
    }

    /**
     * 根据经纬度 构建坐标圈定的多边形
     *
     * @param atlDto
     * @return
     */
    public String formattingPolygon(AtlasPositionDTO atlDto) {
        StringBuffer stringBuffer = new StringBuffer();
        //构建参数 左上角-右上角-右下角-左下角-左上角
        stringBuffer.append("POLYGON((");
        String lt = formattingLonLat(atlDto.getLt());
        stringBuffer.append(lt);
        stringBuffer.append(",");
        String rt = formattingLonLat(atlDto.getRt());
        stringBuffer.append(rt);
        stringBuffer.append(",");
        String rb = formattingLonLat(atlDto.getRb());
        stringBuffer.append(rb);
        stringBuffer.append(",");
        String lb = formattingLonLat(atlDto.getLb());
        stringBuffer.append(lb);
        stringBuffer.append(",");
        stringBuffer.append(lt);
        stringBuffer.append("))");
        return stringBuffer.toString();
    }

}
